import logging

from flask import Blueprint,request,jsonify
from flask_socketio import emit
from app import socketio  # 使用主应用的 socketio 实例
from app.util.result import Result
from app import db
from app.models import Message,User,House,Address
from sqlalchemy import or_, and_
import requests
import time

from datetime import datetime

chat_bp = Blueprint('chat', __name__)
# 全局变量，表示是否要由ai回答
is_ai=0
# 替换为你的 DashScope API Key
DASHSCOPE_API_KEY = "sk-c15c5243cd184608b6eebc4a1b72f209"
# MODEL_NAME = "deepseek-ai/DeepSeek-R1-0528"  # 或者其他你喜欢的模型
# API_URL = f"https://api-inference.huggingface.co/models/{MODEL_NAME}"
# HEADERS = {
#     "Authorization": f"Bearer {HF_TOKEN}"
# }


# 全局用户映射表，存储用户ID和连接ID的映射关系
user_sid_map = {}
# 全局用户映射表，存储用户ID和是否开启ai代理的映射关系
ai_enabled_map = {}
# --------------------------------------------------
# 正确做法：在蓝图外部定义路由和事件处理器
# --------------------------------------------------

# HTTP 路由定义
@chat_bp.route('/connect', methods=['POST'])
def chat_connect():
    print("处理进入聊天请求")
    data = request.get_json()
    print("用户"+data.get('userId')+"连接成功")
    # 查询最近联系人
    recent_contacts = get_recent_contacts(data.get('userId'))
    # 返回连接成功和最近联系人列表
    return Result.success(data={'recentContacts': recent_contacts})

def get_recent_contacts(user_id):
    """
    查询最近联系人
    :param user_id: 当前用户ID
    :return: 最近联系人的列表
    """
    # 查询所有发送给当前用户的消息记录
    user_id=int(user_id)
    received_messages = Message.query.filter(
        Message.target == user_id
    ).order_by(Message.timestamp.desc()).all()

    # 查询最近发送的 10 条消息记录
    sent_messages = Message.query.filter(
        Message.user_id == user_id
    ).order_by(Message.timestamp.desc()).limit(10).all()

    # 合并两部分消息记录
    all_messages = received_messages + sent_messages

    # 提取最近联系人的 target_id 或 user_id
    # set是一种数据结构，用来存储不重复的元素
    recent_contacts = set()
    for msg in all_messages:
        if msg.user_id == user_id:
            recent_contacts.add(msg.target)  # 如果消息是由当前用户发送的，添加接收者
        elif msg.target == user_id:
            recent_contacts.add(msg.user_id) # 如果消息是发给当前用户的，添加发送者

    # 如果没有联系人，则默认添加管理员（假设管理员 ID 为 1）
    if not recent_contacts:
        admin_user = User.query.get(1)
        if admin_user:
         recent_contacts.add(1)
    # 获取这些联系人的用户名
    recent_contacts = User.query.filter(User.id.in_(recent_contacts)).all()
    print(recent_contacts)


    # 格式化返回结果
    result = []
    for contact in recent_contacts:
        is_online = get_user_sid(int(contact.id))
        result.append({
            'target': contact.id,
            'username': contact.username,
            'isOnline': is_online is not None
        })
    if(recent_contacts):
     print("在线状态：", is_online)




    # 返回最近联系人列表
    return result



def get_user_sid(user_id):
    """
    根据用户ID获取其连接ID
    :param user_id: 用户ID
    :return: 用户的连接ID，如果用户不在线则返回None
    """
    return user_sid_map.get(user_id)



# Socket.IO 事件定义
@socketio.on('connect', namespace='/chat')
def handle_connect():
    print(f'客户端连接: {request.sid}')
    # 获取用户ID并转换为整数
    user_id_str = request.args.get('userId')
    try:
        user_id = int(user_id_str)
    except (TypeError, ValueError):
        print("无效的 userId，连接拒绝")
        return False  # 拒绝连接

    # 保存映射
    user_sid_map[user_id] = request.sid
    print(f"用户 {user_id} 连接成功，SID: {request.sid}")
    print("储存的SID：", user_sid_map[user_id])
    # 广播该用户上线的消息给所有其他用户（可优化为只通知好友）
    emit('presence_update', {'userId': user_id, 'isOnline': True}, broadcast=True, namespace='/chat')


@socketio.on('disconnect', namespace='/chat')
def handle_disconnect():
    print(f'客户端断开: {request.sid}')
    # 从用户映射表中移除用户
    user_id = next((k for k, v in user_sid_map.items() if v == request.sid), None)
    if user_id:
        del user_sid_map[user_id]
        print(f"用户 {user_id} 断开连接")
    emit('presence_update', {'userId': user_id, 'isOnline': False}, broadcast=True, namespace='/chat')
# 处理客户端发送的消息
@socketio.on('sendmessage', namespace='/chat')
def handle_chat_message(data):
    """
        接收客户端发送的 message 事件
        :param data: 前端发送的数据对象，格式如：
            {
              user_id: Number,
              target: Number,
              role: Number,
              content: String,
              target: Number,
              timestamp: Number,
              ai: bool
            }
        """
    print(f"服务器收到消息: {data}")
    # 1. 创建新的 Message 对象
    new_message = Message(
        user_id=data.get('user_id'),
        role=data.get('role'),
        content=data.get('content'),
        target=data.get('target'),
        timestamp=data.get('timestamp'),
        is_ai=data.get('ai')
    )
    # 2. 添加并提交到数据库
    try:
        db.session.add(new_message)
        db.session.commit()
        print("消息已成功写入数据库")
    except Exception as e:
        db.session.rollback()  # 出错时回滚事务
        print(f"保存消息失败: {e}")
        return

        # 3. 发送消息给目标用户
    target_user_id = int(data.get('target'))
    if target_user_id:
        # 查询目标用户的连接 ID（sid）
        target_sid = get_user_sid(target_user_id)
        if target_sid:
            # 发送消息给目标用户
            emit('chat_response', {
                'data': {
                    'role': data.get('role'),
                    'user_id': data.get('user_id'),
                    'target': data.get('target'),
                    'content': data.get('content'),
                    'timestamp': data.get('timestamp'),
                    'ai': data.get('ai')
                }
            }, room=target_sid)
            print(f"目标用户 {target_user_id} 在线")
        else:
            print(f"目标用户 {target_user_id} 不在线")
    else:
        print("目标用户 ID 无效")
    # 4. 判断是不是该由ai回答
    sender_sid = request.sid  # 获取发送者的 sid
    target_id = int(data.get('target'))
    target_sid = get_user_sid(target_id)
    if not target_sid:
        ai_enabled_map[target_id]=True

    is_ai = 1 if ai_enabled_map.get(target_id, False) else 0

    if is_ai == 1:  # 如果有 ai=1
        question = data.get('content', '')
        print("ai问题：",question,sender_sid)
        print("sender_sid",sender_sid)
        print("target_sid",target_sid)


        # 调用 AI 接口获取回复
        ai_reply = call_ai(question,target_id)

        # 构造 AI 回复消息
        ai_response_data = {
            'data': {
                'role': data.get('role'),
                'user_id': data.get('target'),     #回复消息，所以反过来
                'target': data.get('user_id'),
                'content': ai_reply,
                'timestamp': data.get('timestamp'),
                'is_ai': 1
            }
        }
        # 将ai回复的消息同步到数据库
        # 1. 创建新的ai Message 对象
        new_message_ai = Message(
            user_id=data.get('target'),
            role=data.get('role'),
            content=ai_reply,
            target=data.get('user_id'),
            timestamp=int(time.time() * 1000),
            is_ai=1
        )
        # 2. 添加并提交到数据库
        try:
            db.session.add(new_message_ai)
            db.session.commit()
            print("消息已成功写入数据库")
        except Exception as e:
            db.session.rollback()  # 出错时回滚事务
            print(f"保存消息失败: {e}")
            return
        # 目标同步消息
        if target_sid:
           emit('ai_response', ai_response_data, room=target_sid)
        # 将 AI 回复返回给发送者
        if sender_sid:
           emit('ai_response', ai_response_data, room=sender_sid)

        print(f"AI 回复已发送给用户 {data.get('user_id')}")
        # 重置is_ai
        is_ai=0
        # return




@chat_bp.route('/history', methods=['GET'])
def chat_history():
    # 获取查询参数
    print("进入历史查询")
    user_id = request.args.get('userId')
    role = request.args.get('role')
    target = request.args.get('target')
    page = request.args.get('page', default=1, type=int)
    page_size = request.args.get('pageSize', default=10, type=int)

    # 参数校验（可选）
    if not all([user_id, role, target]):
        return jsonify({"error": "Missing required parameters"}), 400

    # 构建查询条件
    query = Message.query.filter(
        or_(
            and_(Message.user_id == user_id, Message.target == target),
            and_(Message.user_id == target, Message.target == user_id)
        )
    )

    # 分页查询
    pagination = query.order_by(Message.timestamp.desc()).paginate(page=page, per_page=page_size, error_out=False)
    messages = pagination.items
    total = pagination.total
    messages.reverse()  # 转为正序

    # 返回结果
    result = {
        'total': total,
        'messages': [{
            'id': msg.id,
            'user_id': msg.user_id,
            'role': msg.role,
            'content': msg.content,
            'target': msg.target,
            'timestamp': msg.timestamp.isoformat() if isinstance(msg.timestamp, datetime) else msg.timestamp
        } for msg in messages]
    }
    result_str = Result.success(data=result)
    print("接口返回值:", result_str)
    return result_str
# 心跳事件
@socketio.on('heartbeat', namespace='/chat')
def handle_heartbeat(data):
    user_id = data.get('userId')
    role = data.get('role')

    if not user_id:
        print("心跳包缺少 userId")
        return

    try:
        user_id = int(user_id)
    except ValueError:
        print("无效的 userId 格式")
        return

    # 可选：更新用户最后活跃时间
    print(f"收到心跳包：用户 {user_id} 保持连接中...")

    # 如果需要确认心跳成功返回
    emit('heartbeat_response', {'status': 'ok'})

def query_qwen_api(prompt):
    """
    调用 Hugging Face API 获取 AI 回答
    """
    url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"

    headers = {
        "Authorization": f"Bearer {DASHSCOPE_API_KEY}",
        "Content-Type": "application/json"
    }

    data = {
        "model": "qwen-max",  # 根据需要选择不同的模型版本
        "input": {
            "prompt": prompt,
            "max_length": 512,  # 输出的最大长度
            "top_p": 0.9,  # 核采样参数，值越大越随机
            "temperature": 0.7  # 温度参数，控制输出的多样性
        }
    }

    response = requests.post(url, headers=headers, json=data)

    if response.status_code == 200:
        return response.json()['output']['text']
    else:
        print(f"请求失败，状态码：{response.status_code}, 响应内容：{response.text}")
        return "抱歉，我现在无法回答这个问题。"

def call_ai(question, landlord_id):
    """
    调用 AI 接口进行回复生成
    :param question: 用户问题
    :param landlord_id: 房东ID
    :return: AI 生成的回答
    """
    # 1. 查询房东信息
    landlord = User.query.get(landlord_id)
    if not landlord:
        return "未找到对应的房东信息。"

    username = landlord.username
    phone = landlord.phone if landlord.phone else "未知"

    # 2. 查询该房东名下所有房源
    houses = House.query.filter_by(landlord_id=landlord_id).all()
    if not houses:
        return "该房东暂无发布房源信息。"

    # 3. 构建房源 + 地址信息列表
    house_info_list = []
    for house in houses:
        address = Address.query.get(house.address_id)

        try:
            descriptor = ast.literal_eval(house.descriptor)  # 把字符串转成列表
        except Exception:
            descriptor = []

        house_info = {
            "title": house.title,
            "descriptor": descriptor,
            "house_type": house.house_type,
            "status": house.status,
            "price": float(house.price) if house.price is not None else None,
            "area": house.area,
            "deposit": float(house.deposit) if house.deposit is not None else None,
            "address": {
                "province": address.province if address else "",
                "city": address.city if address else "",
                "district": address.district if address else "",
                "detail": address.detailed_address if address else ""
            }
        }
        house_info_list.append(house_info)

    # 4. 格式化房源信息为自然语言文本（AI 更易理解）
    formatted_house_info = ""
    for idx, info in enumerate(house_info_list, 1):
        full_address = f"{info['address']['city']}{info['address']['district']}{info['address']['detail']}"
        descriptors = ', '.join(info['descriptor']) if info['descriptor'] else '无标签'
        price = f"{int(info['price'])}元/月" if info['price'] else "面议"
        deposit = f"{int(info['deposit'])}元" if info['deposit'] else "面议"

        formatted_house_info += (
            f"【房源 {idx}】\n"
            f"标题：{info['title']}\n"
            f"地址：{full_address}\n"
            f"户型：{info['house_type']} | 面积：{info['area']}㎡ | 租金：{price}\n"
            f"押金：{deposit} | 状态：{'出租中' if info['status'] == 2 else '已租/停用'}\n"
            f"标签：{descriptors}\n"
            "-------------------------\n"
        )

    # 5. 构造 Prompt
    prompt = f"""
你是一个智能客服助手，请根据以下房东和房源信息回答用户问题。

房东信息：
姓名：{username}
联系方式：{phone}

房源信息：
{formatted_house_info.strip()}

用户问题：
{question}

请用简洁自然的中文回答用户问题，不要使用Markdown格式。
"""
    print(prompt)

    # TODO: 这里调用大模型接口（如阿里云 Qwen、百度文心一言等），目前返回示例回答
    # 示例返回（实际应调用 AI 模型）
    # 调用 Hugging Face API
    ai_reply = query_qwen_api(prompt)
    # print(ai_reply)
    return ai_reply

@socketio.on('proxy_status',namespace='/chat')
def handle_proxy_status(data):
    print("ai状态",data)
    user_id = int(data.get('userId'))
    is_ai_enabled = data.get('is_ai')  # True / False
    # 保存该用户的 AI 状态
    ai_enabled_map[user_id] = is_ai_enabled
    print(f"用户 {user_id} 的 AI 状态已更新为: {'开启' if is_ai_enabled else '关闭'}")